home *** CD-ROM | disk | FTP | other *** search
- ## -*-Tcl-*-
- # ###################################################################
- # AlphaTcl - core Tcl engine
- #
- # FILE: "www.tcl"
- # created: 01-01-05 03.08.54
- # last update: 01-01-19 06.45.05
- # Author: Vince Darley
- # E-mail: <vince@santafe.edu>
- # mail: 317 Paseo de Peralta, Santa Fe, NM 87501
- # www: <http://www.santafe.edu/~vince/>
- #
- # modified by rev reason
- # -------- --- --- -----------
- # 4/9/97 VMD 1.0 original
- # ###################################################################
- ##
-
-
- proc forceLoadAE {} {
- return
- # Comment out the above line if your machine is very slow.
- alpha::package require tclAE
- global ALPHA HOME
- catch {makeAlis [file join $HOME $ALPHA]}
- }
-
- proc htmlView {filename} {
- global viewHtmlUsing alpha::platform browserSig htmlViewer
- if {${alpha::platform} == "alpha"} {
- # Is the browserSig set yet?
- if {$browserSig == ""} {
- app::getSig "Please locate your browser :" browserSig
- }
- # Make sure that the .html file is of type $browserSig.
- # We also need to delete any resource fork to ensure
- # that it gets sent to the browser, not Alpha.
- setFileInfo $filename type TEXT
- setFileInfo $filename creator $browserSig
- setFileInfo $filename resourcelen
- }
- eval $htmlViewer($viewHtmlUsing) [list $filename]
- }
-
- proc htmlHelpViewer {filename} {
- global alpha::platform
- if {${alpha::platform} != "alpha" || [catch {nameFromAppl hbwr}]} {
- # This shouldn't have been presented as an option ...
- alertnote "Sorry, the MacOS Help viewer could not be found."
- error "The MacOS Help Viewer could not be found."
- }
- app::launchBack hbwr
- sendOpenEvent noReply 'hbwr' $filename
- switchTo 'hbwr'
- }
-
- proc htmlChooseViewer {filename} {
- global htmlViewer
- set prompt "View \"[file tail $filename]\" using … "
- set options [lremove [array names htmlViewer] "Choose each time"]
- lappend options "(Set WWW preferences to avoid this dialog …)"
- set val [listpick -L "Browser" -p $prompt $options]
- if {$val == "(Set WWW preferences to avoid this dialog …)"} {
- dialog::preferences preferences "WWW"
- } else {
- eval $htmlViewer($val) [list $filename]
- }
- }
-
- namespace eval url {}
-
- ##
- # -------------------------------------------------------------------------
- #
- # "url::mailto" --
- #
- # Generate a mailto url from the given argument pairs. You can then
- # pass the result to 'url::execute' to take action. Note that very
- # long mailto urls seem not to be handled properly, so you may wish
- # to check the length of the 'body' field, if given and take a different
- # action (e.g. put the body on the clip board for the user to handle
- # manually).
- #
- # A typical use is:
- #
- # url::execute [url::maito vince@santafe.edu subject hello body goodbye]
- # -------------------------------------------------------------------------
- ##
- proc url::mailto {address args} {
- set url "mailto:$address"
- set divider "?"
- newforeach {arg value} $args {
- append url $divider $arg = [quote::Url $value]
- set divider "&"
- }
- return $url
- }
-
- # This should carry out the default action of opening/clicking-on
- # a url
- proc url::execute {url} {
- icURL $url
- }
-
- # For url's which ought to be downloaded (e.g. files), this
- # procedure will try to carry that out in preference to opening.
- proc url::download {url} {
- global downloadFolder
- url::fetch $url $downloadFolder
- }
-
- proc url::parse {url} {
- if {![regexp {^([^:]+)://(.*)$} $url dmy type rest]} {
- alertnote "I couldn't understand that url: '$url'"
- error ""
- }
- return [list $type $rest]
- }
-
- proc url::parseFtp {p array} {
- # format is user:pass@host/path
- if {[set at [string first "@" $p]] != -1} {
- # have user etc.
- if {[string first ":" $p] < $at} {
- # have password
- regexp {([^:]+):([^@]+)@(.*)$} $p dummy user pass p
- } else {
- # no password
- regexp {([^@]+)@(.*)$} dummy user p
- set pass ""
- }
- } else {
- set user "anonymous"
- if {[catch {set pass [icGetPref Email]}] || ![string length $pass]} {
- set pass "anonymous"
- }
- }
- regexp {([^/]+)($|/$|/(.*/)([^/]*)$)} $p dummy host dummy path file
- upvar $array a
- array set a [list user $user pass $pass host $host path $path file $file]
- }
-
- proc url::store {url file} {
- set t [url::parse $url]
- set type [lindex $t 0]
- set rest [lindex $t 1]
- switch -- $type {
- "ftp" {
- url::parseFtp $rest i
- set i(file) [file tail $file]
- ftpStore "$file" $i(host) "$i(path)$i(file)" $i(user) $i(pass)
- }
- default {
- alertnote "Don't know how to put '$type' url's"
- error ""
- }
- }
- }
-
- proc url::fetchFrom {url localdir {file ""}} {
- url::fetch ${url}${file} $localdir $file
- }
-
-
- ##
- # -------------------------------------------------------------------------
- #
- # "url::fetch" --
- #
- # Get a precise url into a localdir/file. The url may be a directory,
- # in which case we retrieve a listing.
- #
- # Use url::fetchFrom to fetch a file from a given url-location.
- #
- # Note 'Geni' is the sig of a wish applet I wrote which is augmented
- # with a few procedures to download files via http.
- # Of course it needs the user to install Sun's latest
- # release of Tcl/Tk
- # -------------------------------------------------------------------------
- ##
- proc url::fetch {url localdir {file ""}} {
- set t [url::parse $url]
- set type [lindex $t 0]
- set rest [lindex $t 1]
- if {$file != ""} {
- set to [file join $localdir $file]
- } else {
- set to $localdir
- }
-
- switch -- $type {
- "ftp" {
- url::parseFtp $rest i
- catch {file mkdir [file dirname $localdir]}
- if {[regexp "/$" "$i(path)$i(file)"]} {
- # directory
- ftpList $to $i(host) $i(path) $i(user) $i(pass)
- } else {
- ftpFetch $to $i(host) "$i(path)$i(file)" $i(user) $i(pass)
- }
- }
- "http" {
- if {[file isdirectory $to]} {
- global file::separator
- if {[regexp "\\${file::separator}\$" $url]} {
- set to [file join $to index.html]
- } else {
- set to [file join $to [file tail $url]]
- }
- }
- httpFetch $url $to
- }
- default {
- alertnote "Don't know how to fetch '$type' url's"
- error ""
- }
- }
- return $type
- }
-
- proc httpFetch {url to} {
- global useTclServiceForHttp
- if {[info exists useTclServiceForHttp] && $useTclServiceForHttp} {
- httpCopy ${url} $to
- return
- }
- global httpDownloadSig httpDownloadSigs
- # force loading of AE code to avoid some timeout/ae problems
- if {[info tclversion] < 8.0} { forceLoadAE }
- app::launchAnyOfThese $httpDownloadSigs httpDownloadSig
- if {[file exists $to] && [file isfile $to]} {
- if {[dialog::yesno "Replace [file tail $to]?"]} {
- file delete $to
- } else {
- error "Abort download."
- }
- }
- set fid [alphaOpen $to w]
- close $fid
- if {$httpDownloadSig == "Geni"} {
- switchTo '$httpDownloadSig'
- set res [AEBuild -r -t 30000 '$httpDownloadSig' misc dosc ---- \
- "“[list Http_Copy ${url} $to]”"]
- switchTo 'ALFA'
- if {[string match "*Not found*" $res]} {
- catch {file delete $to}
- error "File not found on http server."
- }
- } else {
- AEBuild -r -t 30000 '$httpDownloadSig' WWW! OURL ---- "“${url}”" \
- INTO [makeAlis "$to"]
- }
- }
-
- # Copy a URL to a file and print meta-data
- proc httpCopy { url file {chunk 4096} } {
- package require http
- set out [alphaOpen $file w]
- set token [http::geturl $url -channel $out -progress httpProgress \
- -blocksize $chunk]
- close $out
- upvar #0 $token state
- set max 0
- foreach {name value} $state(meta) {
- if {[string length $name] > $max} {
- set max [string length $name]
- }
- if {[regexp -nocase ^location$ $name]} {
- # Handle URL redirects
- message "Location:$value"
- return [httpCopy [string trim $value] $file $chunk]
- }
- }
- incr max
- foreach {name value} $state(meta) {
- #puts [format "%-*s %s" $max $name: $value]
- }
- return $token
- }
-
- proc httpProgress {args} {
- message $args
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "ftpFetch" --
- #
- # Downloads a remote file to your disk.
- #
- # -------------------------------------------------------------------------
- ##
- proc ftpFetch {localName host path user password {replyHandler ""}} {
- global useTclServiceForFtp
- file::ensureDirExists [file dirname $localName]
- if {[info exists useTclServiceForFtp] && $useTclServiceForFtp} {
- package require ftp
- set s [ftp::Open $host $user $password -output ftpDisplayMsg]
- if {$s == -1} {
- error "Failed to open ftp connection to $host"
- }
- ftp::Type $s binary
- if {![ftp::Get $s $path $localName]} {
- ftp::Close $s
- error "Problem fetching file"
- }
- ftp::Close $s
- if {[string length $replyHandler]} {
- eval $replyHandler
- }
- return
- }
- global ftpSig ftpSigs
- # force loading of AE code to avoid some timeout/ae problems
- if {[info tclversion] < 8.0} { forceLoadAE }
- app::launchAnyOfThese $ftpSigs ftpSig "Please locate your ftp application:"
- if {[file exists $localName]} {
- file delete $localName
- }
- if {$ftpSig == "FTCh" || $ftpSig == "Arch"} {
- set localName "[file dirname $localName]:"
- set flag -r
- if {$replyHandler != ""} {
- currentReplyHandler $replyHandler
- set flag -q
- }
- }
- switch -- $ftpSig {
- Arch -
- FTCh {AEBuild $flag -t 30000 '$ftpSig' Arch Ftch FTPh "“$host”" FTPc "“$path”" ArGU "“$user”" ArGp "“$password”" ---- [makeAlis $localName]}
- Woof {
- if {$replyHandler == "" || ![checkNetFinderVersion]} {
- set flag -r
- if {$replyHandler != ""} {
- currentReplyHandler $replyHandler
- set flag -q
- }
- close [open $localName "w"]
- AEBuild $flag -t 30000 'Woof' GURL GURL ---- "“ftp://${user}:${password}@${host}/${path}”" dest [makeAlis $localName]
- return
- }
- global PREFS ALPHA
- set Woof [temp::unique ftptmp Woof]
- set fid [open $Woof "w"]
- puts $fid "auto result;"
- puts $fid "auto script;"
- puts $fid "auto script1;"
- puts $fid "auto ftpRef = NFCreateFTPInstance();"
- puts $fid "NFLoadModuleConstants();"
- puts $fid "do \{"
- puts $fid "if (result = NFConnect(ftpRef, \"$host\", 21, \"$user\", \"$password\"), result != 0) break;"
- puts $fid "if (result = NFReceiveFile(ftpRef, \"$path\", eASCIIType, \"$localName\", eText, NULL, NULL), result != 0) break;"
- puts $fid "\} while(0);"
- puts $fid "NFDisconnect(ftpRef);"
- puts $fid "NFDeleteFTPInstance(ftpRef);"
- puts $fid "script = \"tell app \\\"$ALPHA\\\"\\r ignoring application responses \\r DoScript \\\"$replyHandler aevt\\\\\\\\\\\\\\\\ansr\\\\\\\\\\\\\\\\{'----':\" + string(result) + \"\\\\\\\\\\\\\\\\}\";"
- puts $fid "script1 = \"; file delete \{$Woof\}\\\"\\r end ignoring\\r end tell\";"
- puts $fid "MICI.ExecuteScript(script + script1);"
- close $fid
- setFileInfo $Woof type ICI!
- sendOpenEvent noReply 'Woof' $Woof
- }
- }
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "ftpStore" --
- #
- # Uploads a file to a remote ftp server.
- #
- # -------------------------------------------------------------------------
- ##
- proc ftpStore {localName host path user password {replyHandler ftpHandleReply}} {
- global useTclServiceForFtp
- if {[info exists useTclServiceForFtp] && $useTclServiceForFtp} {
- package require ftp
- set s [ftp::Open $host $user $password -output ftpDisplayMsg]
- if {$s == -1} {
- error "Failed to open ftp connection to $host"
- }
- ftp::Type $s binary
- # Note that 'Put' will overwrite existing files.
- if {[catch {ftp::Put $s $localName $path}]} {
- # Most likely cause is sub-paths not existing.
- set pieces [file split [file dirname $path]]
- set sub {}
- foreach piece $pieces {
- set sub [file join $sub $piece]
- ftp::MkDir $s $sub
- }
- ftp::Put $s $localName $path
- }
- ftp::Close $s
- return
- }
- global ftpSig ftpSigs
- # force loading of AE code to avoid some timeout/ae problems
- if {[info tclversion] < 8.0} { forceLoadAE }
- app::launchAnyOfThese $ftpSigs ftpSig "Please locate your ftp application:"
- switch -- $ftpSig {
- Arch -
- FTCh {
- currentReplyHandler $replyHandler
- AEBuild -q -t 30000 '$ftpSig' Arch Stor ---- [makeAlis $localName] FTPh "“$host”" FTPc "“$path”" ArGU "“$user”" ArGp "“$password”"
- }
- Woof {
- set dirpath [string range $path 0 [expr {[string last / $path] - 1}]]
- if {![checkNetFinderVersion]} {
- currentReplyHandler $replyHandler
- AEBuild -q -t 30000 '$ftpSig' PURL PURL ---- [makeAlis $localName] dest "“ftp://${user}:${password}@${host}/${dirpath}”"
- return
- }
- global PREFS ALPHA
- set Woof [temp::unique ftptmp Woof]
- set fid [open $Woof "w"]
- puts $fid "auto result;"
- puts $fid "auto script;"
- puts $fid "auto script1;"
- puts $fid "auto ftpRef = NFCreateFTPInstance();"
- puts $fid "NFLoadModuleConstants();"
- puts $fid "do \{"
- puts $fid "if (result = NFConnect(ftpRef, \"$host\", 21, \"$user\", \"$password\"), result != 0) break;"
- puts $fid "if (result = NFChangeWorkingDirectory(ftpRef, \"$dirpath\"), result != 0) break;"
- puts $fid "if (result = NFSendFile(ftpRef, \"$path\", eASCIIType, \"$localName\", eText, NULL, NULL), result != 0) break;"
- puts $fid "\} while(0);"
- puts $fid "NFDisconnect(ftpRef);"
- puts $fid "NFDeleteFTPInstance(ftpRef);"
- puts $fid "script = \"tell app \\\"$ALPHA\\\"\\r ignoring application responses \\r DoScript \\\"$replyHandler aevt\\\\\\\\\\\\\\\\ansr\\\\\\\\\\\\\\\\{'----':\" + string(result) + \"\\\\\\\\\\\\\\\\}\";"
- puts $fid "script1 = \"; file delete \{$Woof\}\\\"\\r end ignoring\\r end tell\";"
- puts $fid "MICI.ExecuteScript(script + script1);"
- close $fid
- setFileInfo $Woof type ICI!
- sendOpenEvent noReply 'Woof' $Woof
- }
- }
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "ftpList" --
- #
- # Saves the file listing of a remote directory to a file. Uses a trick
- # for Fetch when saving the file. First the files are listed in a text
- # window in Fetch. This window is then saved to the disk.
- #
- # -------------------------------------------------------------------------
- ##
- proc ftpList {localName host path user password {replyHandler ""}} {
- global useTclServiceForFtp
- if {[info exists useTclServiceForFtp] && $useTclServiceForFtp} {
- package require ftp
- set s [ftp::Open $host $user $password -output ftpDisplayMsg]
- if {$s == -1} {
- error "Failed to open ftp connection to $host"
- }
- ftp::Type $s binary
- if {[string length $path]} {
- if {![regexp {/$} $path]} {append path "/"}
- }
- set res [ftp::List $s $path]
- ftp::Close $s
- set fd [alphaOpen $localName "w"]
- puts $fd [join [concat "dummy" $res "dummy"] "\n"]
- close $fd
- if {[string length $replyHandler]} {
- eval $replyHandler
- }
- return
- }
- global ftpSig ftpSigs
- # force loading of AE code to avoid some timeout/ae problems
- if {[info tclversion] < 8.0} { forceLoadAE }
- app::launchAnyOfThese $ftpSigs ftpSig "Please locate your ftp application:"
- switch -- $ftpSig {
- Arch -
- FTCh {
- close [open $localName "w"]
- set flag -r
- if {$replyHandler != ""} {
- currentReplyHandler $replyHandler
- set flag -q
- }
- if {$ftpSig == "Arch"} {
- AEBuild $flag -t 30000 '$ftpSig' Arch List FTPh "“$host”" FTPc "“$path”" ArGU "“$user”" ArGp "“$password”" {----} [makeAlis $localName]
- }
- if {$ftpSig == "FTCh"} {
- AEBuild -r -t 3000 '$ftpSig' Arch List FTPh "“$host”" FTPc "“$path”" ArGU "“$user”" ArGp "“$password”" {----} [makeAlis $localName]
- AEBuild -r -t 3000 'FTCh' FTCh VwFL ---- "obj{want:type(cFWA), from:'null'(), form:name, seld:“$host”}"
- AEBuild -r -t 3000 'FTCh' core save ---- "obj{want:type(cFWC), from:'null'(), form:indx, seld:long(1)}" kfil [makeAlis $localName]
- AEBuild $flag -t 3000 'FTCh' core clos ---- "obj{want:type(cFWC), from:'null'(), form:indx, seld:long(1)}" savo "yes"
- }
-
- if {$ftpSig == "Arch"} {
- set newname [file rootname $localName]#1[file extension $localName]
- getFileInfo $localName arr
- if {$arr(datalen) == 0 && [file exists $newname]} {
- file delete $localName
- file rename $newname $localName
- }
- }
- }
- Woof {
- if {$replyHandler == ""} {
- alertnote "This doesn't work with NetFinder."
- error "no reply handler"
- }
- global PREFS ALPHA
- if {![checkNetFinderVersion]} {
- alertnote "NetFinder 2.1.2 or later required."
- error "too old NetFinder"
- }
- close [open $localName "w"]
- set Woof [temp::unique ftptmp Woof]
- set fid [open $Woof "w"]
- puts $fid "auto file;"
- puts $fid "auto result;"
- puts $fid "auto item;"
- puts $fid "auto script;"
- puts $fid "auto script1;"
- puts $fid {auto listing = [array];}
- puts $fid "auto ftpRef = NFCreateFTPInstance();"
- puts $fid "file = fopen(\"$localName\", \"w\");"
- puts $fid "NFLoadModuleConstants();"
- puts $fid "do \{"
- puts $fid "if (result = NFConnect(ftpRef, \"$host\", 21, \"$user\", \"$password\"), result != 0) break;"
- puts $fid "if (result = NFListDirectory(ftpRef, \"$path\", 1, &listing), result != 0) break;"
- puts $fid "forall(item in listing) \{"
- puts $fid "if ((item.kind & eDirectoryItem) == eDirectoryItem) fprintf(file, \"d \");"
- puts $fid "else if ((item.kind & eLinkItem) == eLinkItem) fprintf(file, \"l \");"
- puts $fid "else fprintf(file, \" \");"
- puts $fid "fprintf(file, \"Ab 0 0 %s\", item.name);"
- puts $fid "if ((item.kind & eLinkItem) == eLinkItem) fprintf(file, \" -> %s\", item.link);"
- puts $fid "fprintf(file, \"\\n\");"
- puts $fid "\}"
- puts $fid "\} while(0);"
- puts $fid "NFDisconnect(ftpRef);"
- puts $fid "NFDeleteFTPInstance(ftpRef);"
- puts $fid "close(file);"
- puts $fid "script = \"tell app \\\"$ALPHA\\\"\\r ignoring application responses \\r DoScript \\\"$replyHandler aevt\\\\\\\\\\\\\\\\ansr\\\\\\\\\\\\\\\\{'----':\" + string(result) + \"\\\\\\\\\\\\\\\\}\";"
- puts $fid "script1 = \"; file delete \{$Woof\}\\\"\\r end ignoring\\r end tell\";"
- puts $fid "MICI.ExecuteScript(script + script1);"
- close $fid
- setFileInfo $Woof type ICI!
- sendOpenEvent noReply 'Woof' $Woof
- }
- default {
- alertnote "This doesn't work with [file tail [nameFromAppl $ftpSig]]."
- }
- }
- }
-
- # Checks the version of NetFinder
- proc checkNetFinderVersion {} {
- global NetFinderVersion
- if {![info exists NetFinderVersion]} {
- alpha::package require version
- # if error, assume recent enough.
- if {[catch {file::version -creator Woof} NetFinderVersion]} {
- set NetFinderVersion "2.1.2"
- return 1
- }
- }
- return [expr {[alpha::package vcompare $NetFinderVersion "2.1.2"] >= 0}]
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "ftpHandleReply" --
- #
- # Handles the reply when using ftpStore.
- #
- # -------------------------------------------------------------------------
- ##
- proc ftpHandleReply {reply} {
- set ans [string range $reply 11 end]
- if {[regexp {^errs:“([^”]+)”} $ans dum err]} {
- # Fetch error
- if {[regexp {Error: (.*)} $err dum err2]} {set err $err2}
- switchTo 'ALFA'
- alertnote "Ftp error: $err"
- } elseif {[regexp {^'----':-?([0-9]*)} $ans dum err]} {
- if {$err != "0"} {
- # Anarchie error.
- switchTo 'ALFA'
- alertnote "Ftp error: $err"
- } else {
- message "Document uploaded to ftp server."
- }
- } elseif {$ans == "\\\}"} {
- message "Document uploaded to ftp server."
- } else {
- return 0
- }
- return 1
- }
-
- # Used by Tcl's 'ftp' package.
- proc ftpDisplayMsg {s msg {state ""}} {
- switch -- $state {
- data {::message $msg}
- control {::message $msg}
- error {::message $msg}
- default {::message $msg}
- }
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "GURLHandler" --
- #
- # Handle general GURL events by extracting the type 'ftp', 'http',… and
- # calling a procedure ${type}GURLHandler with a single parameter which is
- # the extracted resource. Can be put to more general use. You must
- # register this proc as an event handler if you want to use it. Do this
- # with:
- #
- # eventHandler GURL GURL GURLHandler
- #
- # -------------------------------------------------------------------------
- ##
- proc GURLHandler {msg} {
- if {![regsub {.*“(.*)”.*} $msg {\1} gurl]} {
- alertnote "Didn't understand GURL: $msg"
- return
- }
- set GURLtype [lindex [split $gurl ":"] 0]
- set GURLvalue [string range $gurl [expr {1+[string length $GURLtype]}] end]
- if {[catch {${GURLtype}GURLHandler $GURLvalue} msg]} {
- message $msg
- }
- }
-
- proc url::browserWindow {} {
- global tcl_platform browserSig
- switch -- $tcl_platform(platform) {
- "macintosh" {
- if {![regexp {\[([0-9]+)} [AEBuild -r '$browserSig' WWW! LSTW] "" winnum]} {
- error "No browser window."
- }
- # returns window info
- regexp {\[([^ ]+)} [AEBuild -r '$browserSig' WWW! WNFO ---- $winnum] "" winurl
- set winurl [string trim $winurl "“”,"]
- if {$winurl == "'TEXT'()"} {
- error "Empty browser window."
- }
- return $winurl
- }
- "windows" {
- if {[info exists browserSig]} {
- set root [string tolower [file rootname [file tail $browserSig]]]
- } else {
- set root iexplore
- }
- set root [string trim $root ".0123456789"]
- # If multiple iexplore instances are running, this seems
- # to pick the first? This should work for 'iexplore' and
- # 'netscape' names.
- set info [dde request $root WWW_GetWindowInfo 1]
- set url [lindex [split $info \"] 1]
- return $url
- }
- "unix" {
- error "Sorry, this is unimplemented. Please contribute\
- a suitable implementation!"
- }
- }
- }
-
-